using Domain;
using Domain.Quality;
using Domain.工艺工序;
using Domain.生产订单;
using Infratructure;
using Microsoft.AspNetCore.SignalR;
using Team.API.Hubs;

namespace Team.API.Services
{
    /// <summary>
    /// 设备状态服务
    /// 提供设备状态检查和更新的共享逻辑
    /// </summary>
    public interface IEquipmentStatusService
    {
        Task<(int UpdatedCount, List<string> EquipmentNames)> CheckAndUpdateEquipmentStatusAsync(
            string source,
            CancellationToken cancellationToken = default);
    }

    public class EquipmentStatusService : IEquipmentStatusService
    {
        private readonly IServiceProvider _serviceProvider;
        private readonly IHubContext<EquipmentStatusHub> _hubContext;
        private readonly ILogger<EquipmentStatusService> _logger;

        public EquipmentStatusService(
            IServiceProvider serviceProvider,
            IHubContext<EquipmentStatusHub> hubContext,
            ILogger<EquipmentStatusService> logger)
        {
            _serviceProvider = serviceProvider;
            _hubContext = hubContext;
            _logger = logger;
        }

        /// <summary>
        /// 检查并更新设备状态
        /// </summary>
        /// <param name="source">触发来源标识</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>更新的设备数量和设备名称列表</returns>
        public async Task<(int UpdatedCount, List<string> EquipmentNames)> CheckAndUpdateEquipmentStatusAsync(
            string source,
            CancellationToken cancellationToken = default)
        {
            using var scope = _serviceProvider.CreateScope();

            var equipmentRepo = scope.ServiceProvider.GetRequiredService<IRepository<Equipmentmodel>>();
            var productionRepo = scope.ServiceProvider.GetRequiredService<IRepository<Productionschedulemodel>>();
            var orderRepo = scope.ServiceProvider.GetRequiredService<IRepository<OrderModel>>();

            var currentTime = DateTime.Now;
            _logger.LogInformation($"[{source}] 开始检查设备状态 - {currentTime:yyyy-MM-dd HH:mm:ss}");

            // 获取所有数据
            var equipments = equipmentRepo.GetAll().Where(x => !x.IsDel).ToList();
            var schedules = productionRepo.GetAll().Where(x => !x.IsDel).ToList();
            var orders = orderRepo.GetAll().Where(x => !x.IsDel).ToList();

            var equipmentsToUpdate = new List<Equipmentmodel>();
            var updatedEquipmentNames = new List<string>();

            foreach (var equipment in equipments)
            {
                // 只处理使用中的设备（状态3）
                if (equipment.EquipmentStatus != 3)
                    continue;

                // 查找该设备的所有排程记录
                var equipmentSchedules = schedules
                    .Where(x => x.Equipmentid == equipment.Id)
                    .OrderByDescending(x => x.Planendtime)
                    .ToList();

                if (!equipmentSchedules.Any())
                    continue;

                // 获取该设备最后一条排程的结束时间
                var lastSchedule = equipmentSchedules.First();

                // 如果当前时间已经超过最后排程的结束时间
                if (currentTime > lastSchedule.Planendtime)
                {
                    // 检查该设备是否有待处理订单
                    var equipmentOrderIds = equipmentSchedules.Select(x => x.OrderId).Distinct().ToList();
                    var hasPendingOrders = orders.Any(x =>
                        equipmentOrderIds.Contains(x.Id) &&
                        x.Orderstatus == 0); // 状态0：待排程

                    // 如果没有待处理订单，则将设备状态改为空闲
                    if (!hasPendingOrders)
                    {
                        equipment.EquipmentStatus = 2; // 状态2：空闲
                        equipmentsToUpdate.Add(equipment);
                        updatedEquipmentNames.Add(equipment.Equipmentname);

                        _logger.LogInformation($"[{source}] 设备 [{equipment.Equipmentname}] 状态已更新为空闲");
                    }
                }
            }

            // 批量更新设备状态
            if (equipmentsToUpdate.Any())
            {
                await equipmentRepo.UpdateRangeAsync(equipmentsToUpdate);

                var message = $"[{source}] 已更新 {equipmentsToUpdate.Count} 个设备状态为空闲: {string.Join(", ", updatedEquipmentNames)}";
                _logger.LogInformation(message);

                // 通过SignalR推送更新消息给所有客户端
                try
                {
                    await _hubContext.Clients.All.SendAsync(
                        "ReceiveEquipmentStatusUpdate",
                        new
                        {
                            Time = currentTime,
                            Count = equipmentsToUpdate.Count,
                            Equipments = updatedEquipmentNames,
                            Message = message,
                            Source = source
                        },
                        cancellationToken);

                    _logger.LogInformation($"[{source}] 设备状态更新消息已通过SignalR推送");
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, $"[{source}] 推送SignalR消息失败");
                }
            }
            else
            {
                _logger.LogInformation($"[{source}] 没有设备需要更新状态");
            }

            return (equipmentsToUpdate.Count, updatedEquipmentNames);
        }
    }
}
